#include <DynamicLinker.h>
#include <ProcessManager.h>

extern "C" void resolveSymbol_asm(void);

extern "C" Address resolveSymbol(Address library, Address symbol)
{
  Address a = processManager->getProcess()->getLinker()->resolveSymbol(
                                                          library, symbol);
  return a;
}

DynamicLinker::DynamicLinker(Elf32Parser *elf) :
  mainExecutable(elf)
{
  
  // Initialise the ELF program's dynamic translation mechanism.
  // To do this, we insert a library ID (0) in GOT+4 (Global offset table)
  // and the address of resolveSymbol into GOT+8.
  
  // Get the global offset table address.
  Address *got = (Address*)mainExecutable->getGlobalOffsetTable();
  DEBUG_VERBOSE("Found Global offset table at " << hex << (u32int)got << ": " << elf->filename);
  if (got)
  {
    got++;      // Go to GOT+4
    *got = 0; // Library ID = 0.
    got++;
    *got   = (Address)&::resolveSymbol_asm;
  }
  
}


DynamicLinker::~DynamicLinker()
{
}

Address DynamicLinker::resolveSymbol(Address library, Address symbol)
{
  // If the library address is NULL, this lookup is coming from the 
  // main program, not an auxiliary library.
  if (!library)
  {
    // Get the actual symbol structure for this symbol.
    Address *location = (Address*) 
                        mainExecutable->findDynamicSymbolLocation(symbol);

    // Get the symbol name for this symbol.
    char *name = mainExecutable->findDynamicSymbolName(symbol);
    // Find the specified symbol.
    Address relocate = kernelElfParser.findSymbol(name);
    if (relocate == 0)
    {
      kerr << "Looking up symbol '" << name << "' failed!" << endl;
      PANIC("Symbol resolution failure!");
    }
    // TODO: iterate over all loaded libraries to find this symbol.
    
    // Write the relocated symbol at the correct address.
    *location = relocate;
// kerr << "Relocation " << relocate << " for " << name << endl;
    // Return the relocated address, so our global function can jump to it.
    return relocate;
  }
  else
  {
    PANIC("Shared libraries not implemented.");
  }
}
